#include "tremo_regs.h"
#include "tremo_rcc.h"
#include "tremo_delay.h"


#define DDL_TICK_FREQ_DEFAULT 1000
#define DDL_TICK_IRQ_PRIORITY ((1 <<__NVIC_PRIO_BITS) - 1)

__IO uint32_t uwTick;
__IO uint32_t SysTickClock = 24000000;

/**
 * @brief Init the registers used in delay function
 * @param None
 * @retval None
 */
void delay_init(void)
{
    SysTickClock = rcc_get_clk_freq(RCC_HCLK);
    if (SysTickClock < 1000000)
        return;

    SysTick_Config(SysTickClock / DDL_TICK_FREQ_DEFAULT);
    NVIC_SetPriority(SysTick_IRQn, DDL_TICK_IRQ_PRIORITY);
}

/**
 * @brief Delay some microseconds
 * @param nus The delay in microsecond
 * @retval None
 */
void delay_us(uint32_t nus)
{
    uint32_t last, now, reload, ticks, sub = 0;
    last = SysTick->VAL;
    reload = SysTick->LOAD;
    ticks = SysTickClock / 1000000UL * nus;

    while (ticks > sub)
    {
        ticks -= sub;
        now = SysTick->VAL;
        sub = last >= now ? last - now : reload + last - now;
        last = now;
    }
}

/**
 * @brief Delay some milliseconds
 * @param nms The delay in millisecond
 * @retval None
 */
void delay_ms(uint32_t nms)
{
    uint32_t tickstart = get_tick();
    uint32_t wait = nms;

    wait++;

    while ((get_tick() - tickstart) < wait);
}

uint32_t get_tick(void)
{
    return uwTick;
}

void suspend_tick(void)
{
    /* Disable SysTick Interrupt */
    SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
}

void resume_tick(void)
{
    /* Enable SysTick Interrupt */
    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
}

/**
 * @brief  This function handles SysTick Handler.
 * @param  None
 * @retval None
 */
void SysTick_Handler(void)
{
    NVIC_ClearPendingIRQ(SysTick_IRQn);
    uwTick++;
}